package cn.easyplatform.studio.web.editors.help;

import cn.easyplatform.entities.beans.list.ListBean;
import cn.easyplatform.entities.beans.page.PageBean;
import cn.easyplatform.entities.beans.project.DeviceMapBean;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.studio.StudioApp;
import cn.easyplatform.studio.cmd.entity.GetAndLockEntityCmd;
import cn.easyplatform.studio.cmd.entity.QueryCmd;
import cn.easyplatform.studio.cmd.identity.GetPageXmlCmd;
import cn.easyplatform.studio.context.Contexts;
import cn.easyplatform.studio.utils.FileUtil;
import cn.easyplatform.studio.utils.GlobalVariableService;
import cn.easyplatform.studio.utils.StudioServiceFileUtils;
import cn.easyplatform.studio.utils.WebUtils;
import cn.easyplatform.studio.vos.ElementVo;
import cn.easyplatform.studio.vos.EntityVo;
import cn.easyplatform.studio.vos.GetEntityVo;
import cn.easyplatform.studio.vos.QueryResultVo;
import cn.easyplatform.studio.web.editors.AbstractPanelEditor;
import cn.easyplatform.studio.web.editors.support.CodeFormatter;
import cn.easyplatform.studio.web.editors.support.ZulXsdUtil;
import cn.easyplatform.studio.web.layout.WorkbenchController;
import cn.easyplatform.studio.web.views.impl.AppElementView;
import cn.easyplatform.type.DeviceType;
import com.alibaba.fastjson.JSON;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.OpenEvent;
import org.zkoss.zul.*;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class WidgetIDEditor extends AbstractPanelEditor {
    private enum EditStatus {
        EDIT_CREATE, EDIT_CREATE_CHANGE, EDIT_SELECT, EDIT_SELECT_CHANGE
    }

    private Toolbarbutton createBtn;

    private Toolbarbutton saveBtn;

    private Toolbarbutton deleteBtn;

    private Bandbox searchEntityBandbox;

    private Bandbox searchIDBandbox;

    private Listbox listbox;

    private Textbox entityIdTextbox;

    private Textbox elementTextbox;

    private Textbox pathTextbox;

    private Textbox eventTextbox;

    private List<ElementVo> allElement;

    private ElementVo selectElement;

    private WidgetIDEditor.EditStatus editStatus = WidgetIDEditor.EditStatus.EDIT_CREATE;

    public WidgetIDEditor(WorkbenchController workbench, String id) {
        super(workbench, id);
    }

    @Override
    protected void dispatch(Event evt) {
        //创建
        if (evt.getTarget().equals(createBtn)) {
            if (editStatus == EditStatus.EDIT_SELECT_CHANGE || editStatus == EditStatus.EDIT_CREATE_CHANGE)
                WebUtils.showConfirm(Labels.getLabel("button.save"), new EventListener<Event>() {
                    @Override
                    public void onEvent(Event event) throws Exception {
                        if (event.getName().equals(Events.ON_OK))
                            Events.postEvent(new Event(Events.ON_CLICK, saveBtn));
                        else {
                            editStatus = EditStatus.EDIT_CREATE;
                            showHeaderBtns();
                            selectElement = new ElementVo();
                            setValue();
                        }
                    }
                });
            else {
                editStatus = EditStatus.EDIT_CREATE;
                showHeaderBtns();
                selectElement = new ElementVo();
                setValue();
            }
        } else if (evt.getTarget().equals(saveBtn)) {
            if (Strings.isBlank(elementTextbox.getValue())) {
                elementTextbox.setFocus(true);
                throw new WrongValueException(elementTextbox, Labels.getLabel(
                        "message.no.empty", new Object[]{Labels.getLabel("guide.step.element")}));
            } else if (Strings.isBlank(selectElement.getElementId())) {
                //添加
                setMessage();
                allElement.add(selectElement);
                Boolean saveSuccess = saveToFile(allElement);
                if (saveSuccess) {
                    WebUtils.showSuccess(Labels.getLabel("button.save"));
                    List<ElementVo> elementVos = new ArrayList<>();
                    elementVos.add(selectElement);
                    isDoubleID(allElement, elementVos);
                    search(searchEntityBandbox.getValue(), searchIDBandbox.getValue());
                    editStatus = EditStatus.EDIT_CREATE;
                    showHeaderBtns();
                } else {
                    selectElement = new ElementVo();
                    WebUtils.showError(Labels.getLabel("message.error", new String[]{Labels.getLabel("button.save")}));
                    return;
                }
            } else {
                //更新
                setMessage();
                Boolean saveSuccess = saveToFile(allElement);
                if (saveSuccess) {
                    WebUtils.showSuccess(Labels.getLabel("button.save"));
                    List<ElementVo> elementVos = new ArrayList<>();
                    elementVos.add(selectElement);
                    isDoubleID(allElement, elementVos);
                    search(searchEntityBandbox.getValue(), searchIDBandbox.getValue());
                    editStatus = EditStatus.EDIT_SELECT;
                    showHeaderBtns();
                } else {
                    WebUtils.showError(Labels.getLabel("message.error", new String[]{Labels.getLabel("button.save")}));
                }
            }
        } else if (evt.getTarget().equals(deleteBtn)) {
            //删除
            if (selectElement.getEntityId() == null) {
                WebUtils.showError(Labels.getLabel("editor.select",
                        new String[]{Labels.getLabel("guide.step.element")}));
                return;
            }
            WebUtils.showConfirm(Labels.getLabel("button.delete"), new EventListener<Event>() {
                @Override
                public void onEvent(Event event) throws Exception {
                    if (event.getName().equals(Events.ON_OK)) {
                        String elementId = selectElement.getElementId();
                        allElement.remove(selectElement);
                        Boolean saveSuccess = saveToFile(allElement);
                        if (saveSuccess == true) {
                            WebUtils.showSuccess(Labels.getLabel("button.delete"));
                            getSelectedRow().detach();
                            isDoubleIDInDelete(allElement, elementId);
                            search(searchEntityBandbox.getValue(), searchIDBandbox.getValue());
                            selectElement = new ElementVo();
                            setValue();
                            editStatus = EditStatus.EDIT_CREATE;
                            showHeaderBtns();
                        }
                    }
                }
            });
        } else if (evt.getTarget().getId().equals("widgetID_toolbarbutton_extract")) {
            //提取
            List<ElementVo> addElementVos = canAddExtract(getAllExtract());
            allElement.addAll(addElementVos);
            Boolean saveSuccess = saveToFile(allElement);
            if (saveSuccess) {
                WebUtils.showSuccess(Labels.getLabel("button.save"));
                search(searchEntityBandbox.getValue(), searchIDBandbox.getValue());
                editStatus = EditStatus.EDIT_CREATE;
                showHeaderBtns();
            } else {
                selectElement = new ElementVo();
                WebUtils.showError(Labels.getLabel("message.error", new String[]{Labels.getLabel("button.save")}));
                return;
            }
        } else if (evt.getTarget() instanceof Textbox && evt.getName().equals(Events.ON_CHANGE)) {
            //写入
            if (editStatus == EditStatus.EDIT_CREATE)
                editStatus = EditStatus.EDIT_CREATE_CHANGE;
            else if (editStatus == EditStatus.EDIT_SELECT)
                editStatus = EditStatus.EDIT_SELECT_CHANGE;
            showHeaderBtns();
        } else if (evt.getTarget().getId().equals("widgetID_button_entityId")) {
            //跳转
            if (!Strings.isBlank(entityIdTextbox.getValue()))
                openEditor(evt.getTarget(), entityIdTextbox.getValue());
        } else if (evt.getTarget() instanceof Bandbox) {
            //搜索框
            selectElement = new ElementVo();
            setValue();
            String val = null;
            if (evt instanceof OpenEvent) {
                OpenEvent event = (OpenEvent) evt;
                val = (String) event.getValue();
                if (event.getTarget().equals(searchEntityBandbox))
                    searchEntityBandbox.setValue(val);
                else
                    searchIDBandbox.setValue(val);
            } else {
                if (evt.getTarget().equals(searchEntityBandbox))
                    val = searchEntityBandbox.getValue();
                else
                    val = searchIDBandbox.getValue();
            }
            //搜索
            if (evt.getTarget().equals(searchEntityBandbox)) {
                String otherVal = searchIDBandbox.getValue();
                search(val, otherVal);
            } else {
                String  otherVal = searchEntityBandbox.getValue();
                search(otherVal, val);
            }

        } else if (evt.getTarget() instanceof Listitem) {
            //选择
            final Listitem row = (Listitem) evt.getTarget();
            //列表行点击
            if (editStatus == EditStatus.EDIT_SELECT_CHANGE || editStatus == EditStatus.EDIT_CREATE_CHANGE)
                WebUtils.showConfirm(Labels.getLabel("button.save"), new EventListener<Event>() {
                    @Override
                    public void onEvent(Event event) throws Exception {
                        if (event.getName().equals(Events.ON_OK))
                            Events.postEvent(new Event(Events.ON_CLICK, saveBtn));
                        else {
                            selectElement = row.getValue();
                            editStatus = EditStatus.EDIT_SELECT;
                            showHeaderBtns();
                            setValue();
                        }
                    }
                });
            else {
                selectElement = row.getValue();
                editStatus = EditStatus.EDIT_SELECT;
                showHeaderBtns();
                setValue();
            }
        }
    }

    @Override
    public void create(Object... args) {
        Idspace is = createPanel(Labels.getLabel("menu.app.guide.widgetID"),
                "~./images/config.png", "~./include/help/WidgetID.zul");
        createBtn = (Toolbarbutton) is.getFellow("widgetID_toolbarbutton_add");
        createBtn.addEventListener(Events.ON_CLICK, this);
        deleteBtn = (Toolbarbutton) is.getFellow("widgetID_toolbarbutton_delete");
        deleteBtn.addEventListener(Events.ON_CLICK, this);
        saveBtn = (Toolbarbutton) is.getFellow("widgetID_toolbarbutton_save");
        saveBtn.addEventListener(Events.ON_CLICK, this);
        Toolbarbutton extractBtn = (Toolbarbutton) is.getFellow("widgetID_toolbarbutton_extract");
        extractBtn.addEventListener(Events.ON_CLICK, this);
        searchEntityBandbox = (Bandbox) is.getFellow("widgetID_bandbox_entitySearch");
        searchEntityBandbox.addEventListener(Events.ON_OK, this);
        searchEntityBandbox.addEventListener(Events.ON_OPEN, this);
        searchIDBandbox = (Bandbox) is.getFellow("widgetID_bandbox_IDSearch");
        searchIDBandbox.addEventListener(Events.ON_OK, this);
        searchIDBandbox.addEventListener(Events.ON_OPEN, this);
        listbox = (Listbox) is.getFellow("widgetID_listbox_tables");
        entityIdTextbox = (Textbox) is.getFellow("widgetID_textbox_entityId");
        entityIdTextbox.addEventListener(Events.ON_CHANGE, this);
        Button entityIdButton = (Button) is.getFellow("widgetID_button_entityId");
        entityIdButton.addEventListener(Events.ON_CLICK, this);
        elementTextbox = (Textbox) is.getFellow("widgetID_textbox_element");
        elementTextbox.addEventListener(Events.ON_CHANGE, this);
        pathTextbox = (Textbox) is.getFellow("widgetID_textbox_path");
        pathTextbox.addEventListener(Events.ON_CHANGE, this);
        eventTextbox = (Textbox) is.getFellow("widgetID_textbox_event");
        eventTextbox.addEventListener(Events.ON_CHANGE, this);

        AppElementView.getNewElementVos();
        isDoubleID(GlobalVariableService.getInstance().getAppElementList(), GlobalVariableService.getInstance().getAppElementList());
        allElement = GlobalVariableService.getInstance().getAppElementList();
        selectElement = new ElementVo();
        search(null,null);
        showHeaderBtns();
    }

    //数据处理
    private void search(String entityStr, String idStr) {
        List<ElementVo> elementVos = new ArrayList<>();
        if (Strings.isBlank(entityStr) && Strings.isBlank(idStr)) {
            elementVos.addAll(allElement);
        } else {
            //查找参数ID
            if (Strings.isBlank(entityStr)) {
                elementVos.addAll(allElement);
            } else {
                for (ElementVo vo : allElement) {
                    if (Strings.isBlank(vo.getEntityId()) == false && vo.getEntityId().toLowerCase().contains(entityStr.toLowerCase()))
                        elementVos.add(vo);
                }
            }
            //查找目标ID
            if (Strings.isBlank(idStr) == false) {
                //保存需要删除的下标
                List<Integer> deleteElementStr = new ArrayList<>();
                for (int index = 0; index < elementVos.size(); index++) {
                    if (Strings.isBlank(elementVos.get(index).getElementId()) == false &&
                            elementVos.get(index).getElementId().toLowerCase().contains(idStr.toLowerCase())){

                    } else
                        deleteElementStr.add(index);
                }

                //删除正确的下标
                for (int index = 0; index < deleteElementStr.size(); index++) {
                    int deleteIndex = deleteElementStr.get(index);
                    deleteIndex -= index;
                    if (deleteIndex >= 0)
                        elementVos.remove(deleteIndex);
                }
            }
        }

        listbox.getItems().clear();
        createTables(elementVos);
    }

    private void isDoubleID(List<ElementVo> allElement, List<ElementVo> verifyElement) {
        for (int index = 0; index < verifyElement.size(); index++) {
            ElementVo vo = verifyElement.get(index);
            for (int allIndex = 0; allIndex < allElement.size(); allIndex++) {
                ElementVo allVo = allElement.get(allIndex);
                vo.setDoubleId(false);
                if (allVo != vo && allVo.getElementId().equals(vo.getElementId())) {
                    vo.setDoubleId(true);
                    allVo.setDoubleId(true);
                    break;
                }
            }
        }
    }

    private void isDoubleIDInDelete(List<ElementVo> allElement, String deleteElementStr) {
        List<ElementVo> searchElementVos = new ArrayList<>();
        for (int allIndex = 0; allIndex < allElement.size(); allIndex++) {
            ElementVo allVo = allElement.get(allIndex);
            if (allVo.getElementId().equals(deleteElementStr)) {
                searchElementVos.add(allVo);
            }
        }
        //有一个返回结果的时候，把这个DoubleId设置为false
        if (searchElementVos.size() == 1)
            searchElementVos.get(0).setDoubleId(false);
    }
    private boolean saveToFile(List<ElementVo> elementVos) {
        String elementPath = new StudioServiceFileUtils().element_app + File.separator + "element.json";
        if (new File(elementPath).exists() == false) {
            try {
                new File(elementPath).createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        String contentStr = JSON.toJSONString(elementVos);
        return FileUtil.setStreamWithFile(contentStr, elementPath);
    }

    private void setMessage() {
        selectElement.setEntityId(entityIdTextbox.getValue());
        selectElement.setElementId(elementTextbox.getValue());
        selectElement.setElementPath(pathTextbox.getValue());
        selectElement.setAction(pathTextbox.getAction());
    }

    private List<ElementVo> getAllExtract() {
        QueryResultVo result = StudioApp.execute(searchEntityBandbox, new QueryCmd("Page,Datalist", 0));
        List<ElementVo> elementNameList = new ArrayList<>();
        List<String> contents = new ArrayList<>();
        List<String> entityTypes = new ArrayList<>();
        //获取参数里面的代码
        for (EntityVo entityVo : result.getEntities()) {
            GetEntityVo ge = StudioApp
                    .execute(searchEntityBandbox, new GetAndLockEntityCmd(entityVo.getId()));
            String content = "";
            if (entityVo.getType().equals("Page")) {
                PageBean pageBean = (PageBean)ge.getEntity();
                if (Strings.isBlank(pageBean.getAjax()) == false)
                    content = CodeFormatter.formatXML(ZulXsdUtil.buildDocument(pageBean.getAjax()));
            } else if (entityVo.getType().equals("Datalist")) {
                ListBean listBean = (ListBean)ge.getEntity();
                if (Strings.isBlank(listBean.getPanel()) == false)
                    content = CodeFormatter.formatXML(ZulXsdUtil.buildDocument(listBean.getPanel()));
            }
            if (content != null) {
                contents.add(content);
                entityTypes.add(entityVo.getId());
            }
        }
        //获取模板代码
        for (DeviceMapBean dm : Contexts.getProject().getDevices()) {
            if (dm.getType().equals(DeviceType.AJAX.getName())) {
                if (dm.getName().equals("Ajax浏览器")) {
                    if(Strings.isBlank(dm.getLoginPage()) == false){
                        contents.add(dm.getLoginPage());
                        entityTypes.add(Labels.getLabel("menu.project.pc.login"));
                    }else{
                        if(dm.getLoginId()!=0){
                            String loginString = StudioApp.execute(new GetPageXmlCmd(dm.getLoginId()));
                            if (Strings.isBlank(loginString) == false) {
                                contents.add(loginString);
                                entityTypes.add(Labels.getLabel("menu.project.pc.login"));
                            }
                        }
                    }
                    if(Strings.isBlank(dm.getMainPage()) == false){
                        contents.add(dm.getMainPage());
                        entityTypes.add(Labels.getLabel("menu.project.pc.main"));
                    }else{
                        if(dm.getMainId()!=0){
                            String mainString = StudioApp.execute(new GetPageXmlCmd(dm.getMainId()));
                            if (Strings.isBlank(mainString) == false) {
                                contents.add(mainString);
                                entityTypes.add(Labels.getLabel("menu.project.pc.main"));
                            }
                        }
                    }
                }
                else {
                    if(Strings.isBlank(dm.getLoginPage()) == false){
                        contents.add(dm.getLoginPage());
                        entityTypes.add(Labels.getLabel("menu.project.mobile.login"));
                    }else{
                        if(dm.getLoginId()!=0){
                            String loginString = StudioApp.execute(new GetPageXmlCmd(dm.getLoginId()));
                            if (Strings.isBlank(loginString) == false) {
                                contents.add(loginString);
                                entityTypes.add(Labels.getLabel("menu.project.mobile.login"));
                            }
                        }
                    }
                    if(null != dm.getMainPage()&&!"".equals(dm.getMainPage())){
                        contents.add(dm.getMainPage());
                        entityTypes.add(Labels.getLabel("menu.project.mobile.main"));
                    }else{
                        if(dm.getMainId()!=0){
                            String mainString = StudioApp.execute(new GetPageXmlCmd(dm.getMainId()));
                            if (Strings.isBlank(mainString) == false) {
                                contents.add(mainString);
                                entityTypes.add(Labels.getLabel("menu.project.mobile.main"));
                            }
                        }
                    }
                }
            }
        }

        for (int index = 0; index < contents.size(); index++) {
            String content = contents.get(index);
            //正则表达式搜索
            String tableComment = "(id=\"(.*?)\")+";//(setId\("(.*?)"\))+
            Pattern pattern = Pattern.compile(tableComment) ;
            Matcher matcher = pattern.matcher(content) ;
            while(matcher.find()){
                int count = matcher.groupCount() ;
                for (int i = 0; i <= count; i++) {
                    System.out.println(matcher.group(i));
                    if (i % 3 == 2) {
                        String ret = matcher.group(i);
                        ElementVo vo = new ElementVo();
                        vo.setEntityId(entityTypes.get(index));
                        vo.setElementId(ret);
                        vo.setElementPath("");
                        vo.setAction("");
                        elementNameList.add(vo);
                    }
                }
            }
        }
        return elementNameList;
    }

    private List<ElementVo> canAddExtract(List<ElementVo> elementVos) {
        List<ElementVo> elementVoList = new ArrayList<>();
        for (ElementVo vo : elementVos) {
            boolean canAdd = true;
            for (ElementVo allVo : allElement) {
                if (Strings.isBlank(vo.getEntityId()) == false && Strings.isBlank(allVo.getEntityId()) == false
                        && vo.getEntityId().equals(allVo.getEntityId()) && vo.getElementId().equals(allVo.getElementId())) {
                    canAdd = false;
                    break;
                }
            }
            if (canAdd == true) {
                vo.setDoubleId(false);
                elementVoList.add(vo);
            }
        }
        return elementVoList;
    }
    //页面处理
    private void createTables(List<ElementVo> elementVos) {
        List<Listitem> items = listbox.getItems();
        for (ElementVo vo : elementVos) {
            Listitem ti = new Listitem();
            ti.appendChild(new Listcell(vo.getEntityId()));
            ti.appendChild(new Listcell(vo.getElementId()));
            ti.setValue(vo);
            ti.addEventListener(Events.ON_CLICK, this);
            if (vo.isDoubleId() == true)
                ti.appendChild(new Listcell(null, "~./images/error_status.png"));
            else
                ti.appendChild(new Listcell(null, "~./images/correct_status.png"));
            items.add(ti);
        }
    }

    private void setValue() {
        entityIdTextbox.setValue(selectElement.getEntityId());
        elementTextbox.setValue(selectElement.getElementId());
        pathTextbox.setValue(selectElement.getElementPath());
        eventTextbox.setValue(selectElement.getAction());
    }

    private void showHeaderBtns() {
        if (editStatus == WidgetIDEditor.EditStatus.EDIT_CREATE) {
            saveBtn.setDisabled(true);
            deleteBtn.setDisabled(true);
        } else if (editStatus == WidgetIDEditor.EditStatus.EDIT_CREATE_CHANGE || editStatus == WidgetIDEditor.EditStatus.EDIT_SELECT_CHANGE) {
            saveBtn.setDisabled(false);
            deleteBtn.setDisabled(true);
        } else if (editStatus == WidgetIDEditor.EditStatus.EDIT_SELECT) {
            saveBtn.setDisabled(true);
            deleteBtn.setDisabled(false);
        }
    }

    private Listitem getSelectedRow() {
        if (selectElement == null)
            return null;
        return listbox.getSelectedItem();
    }

    private void openEditor(Component ref, String id) {
        if (!id.startsWith("$") && workbench.checkEditor(id) == null) {
            GetEntityVo ge = StudioApp
                    .execute(ref, new GetAndLockEntityCmd(id));
            if (ge != null) {
                char code = 'U';
                if (!Strings.isBlank(ge.getLockUser())) {
                    code = 'R';
                    Messagebox.show(
                            Labels.getLabel("enitiy.locked",
                                    new String[]{ge.getLockUser()}),
                            Labels.getLabel("message.title.error"),
                            Messagebox.OK, Messagebox.INFORMATION);
                }
                workbench.createEditor(ge.getEntity(), code);
            }
        }
    }
}
